if (!window.chrome) {
    // Use the exact property descriptor found in headful Chrome
    // fetch it via `Object.getOwnPropertyDescriptor(window, 'chrome')`
    Object.defineProperty(window, 'chrome', {
        writable: true,
        enumerable: true,
        configurable: false, // note!
        value: {} // We'll extend that later
    })
}

// That means we're running headful and don't need to mock anything
if ('loadTimes' in window.chrome) {
    console.log("处于有头模式中....")
} else {
    // Check that the Navigation Timing API v1 + v2 is available, we need that
    if (
        window.performance ||
        window.performance.timing ||
        window.PerformancePaintTiming
    ) {

        const {performance} = window

        // Some stuff is not available on about:blank as it requires a navigation to occur,
        // let's harden the code to not fail then:
        const ntEntryFallback = {
            nextHopProtocol: 'h2',
            type: 'other'
        }

        // The API exposes some funky info regarding the connection
        const protocolInfo = {
            get connectionInfo() {
                const ntEntry =
                    performance.getEntriesByType('navigation')[0] || ntEntryFallback
                return ntEntry.nextHopProtocol
            },
            get npnNegotiatedProtocol() {
                // NPN is deprecated in favor of ALPN, but this implementation returns the
                // HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
                const ntEntry =
                    performance.getEntriesByType('navigation')[0] || ntEntryFallback
                return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)
                    ? ntEntry.nextHopProtocol
                    : 'unknown'
            },
            get navigationType() {
                const ntEntry =
                    performance.getEntriesByType('navigation')[0] || ntEntryFallback
                return ntEntry.type
            },
            get wasAlternateProtocolAvailable() {
                // The Alternate-Protocol header is deprecated in favor of Alt-Svc
                // (https://www.mnot.net/blog/2016/03/09/alt-svc), so technically this
                // should always return false.
                return false
            },
            get wasFetchedViaSpdy() {
                // SPDY is deprecated in favor of HTTP/2, but this implementation returns
                // true for HTTP/2 or HTTP2+QUIC/39 as well.
                const ntEntry =
                    performance.getEntriesByType('navigation')[0] || ntEntryFallback
                return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)
            },
            get wasNpnNegotiated() {
                // NPN is deprecated in favor of ALPN, but this implementation returns true
                // for HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
                const ntEntry =
                    performance.getEntriesByType('navigation')[0] || ntEntryFallback
                return ['h2', 'hq'].includes(ntEntry.nextHopProtocol)
            }
        }

        const {timing} = window.performance

// Truncate number to specific number of decimals, most of the `loadTimes` stuff has 3
        function toFixed(num, fixed) {
            var re = new RegExp('^-?\\d+(?:.\\d{0,' + (fixed || -1) + '})?')
            return num.toString().match(re)[0]
        }

        const timingInfo = {
            get firstPaintAfterLoadTime() {
                // This was never actually implemented and always returns 0.
                return 0
            },
            get requestTime() {
                return timing.navigationStart / 1000
            },
            get startLoadTime() {
                return timing.navigationStart / 1000
            },
            get commitLoadTime() {
                return timing.responseStart / 1000
            },
            get finishDocumentLoadTime() {
                return timing.domContentLoadedEventEnd / 1000
            },
            get finishLoadTime() {
                return timing.loadEventEnd / 1000
            },
            get firstPaintTime() {
                const fpEntry = performance.getEntriesByType('paint')[0] || {
                    startTime: timing.loadEventEnd / 1000 // Fallback if no navigation occured (`about:blank`)
                }
                return toFixed(
                    (fpEntry.startTime + performance.timeOrigin) / 1000,
                    3
                )
            }
        }

        window.chrome.loadTimes = function () {
            return {
                ...protocolInfo,
                ...timingInfo
            }
        }
        utils.patchToString(window.chrome.loadTimes)
    }
}

